#include<iostream>
#include<func.h>
#include<string>
using std::ostream;
using std::cout;
using std::endl;

//这版本是假如了代理模式 来解决下标问题
//要实现一个写时复制的cowstring
class CowString{

    //str1[0] 
    class charProxy{
    public:
        charProxy(CowString &self, int idx)
        :_self(self)
        ,index(idx)
        {
            //<<

        }
    char& operator=(char ch){
        if(index > 0 && index< _self.use_count()){
            //合法
            if(_self.use_count()>1){
                //进行深拷贝
                _self.delerefKey(); //引用技术-1
                char*ptemp = _self.malloc(_self._pstr);
                strcpy(ptemp,_self._pstr);
                //改变指向
                _self._pstr = ptemp;
                //引用计数设为1
                _self.refinit();
            }
            //如果==0 就不进入上面的循环
            _self._pstr[index] = ch;         
            return _self._pstr[index];
        }else{
            cout<<"访问不合法"<<endl;
            static char nullpchar = '\0';
            return nullpchar;
        }
    }
    friend
    //改值
    ostream& operator<<(ostream&os,const CowString::charProxy&rhs);
    private:
        CowString &_self;
        int index;
    };
private:
    //对key的操作
    //初始化
    void refinit(){
        //找到pstr的前面位置 并设置为1
        *(int*)(_pstr - refKeynumber) = 1;
    }
    //访问
    //add refkeynumber
    void addrefKey(){
        ++*(int*)(_pstr - refKeynumber);
    }
    //delete refkeynumber
    void delerefKey(){
        --*(int*)(_pstr - refKeynumber);
    }
    //这里应该是缺省调用
    char*malloc(const char*pstr = nullptr){
        if(pstr == nullptr){
            return new char[1+refKeynumber]()+refKeynumber;
        }else{
            return new char[strlen(pstr)+refKeynumber]()+refKeynumber;
            cout<<"char*malloc(const char*pstr = nullptr)"<<endl;
        }
    }

    void release(){
        delerefKey();
        if(use_count() == 0){
            //删除原本的
            delete [] (_pstr - refKeynumber);
            _pstr = nullptr;
        }
    }

public:
    //访问数据
    int use_count(){
        return *(int*)(_pstr - refKeynumber);
    }

    CowString()
    :_pstr(malloc()){
        //引用技术+1
        refinit();
        cout<<"Cowstring()"<<endl;
    }
    CowString(const char*pstr)
    :_pstr(malloc(pstr))
    {
        cout<<"Cowstring(const char*pstr)"<<endl;
        //引用技术要+1
        strcpy(_pstr,pstr);
        refinit();
    }
    ~CowString(){
        //要判断当前的值是否为0
        if(use_count() == 0){
            //回收该字符串
            //delete [] _pstr; 这里犯了个错误 没有回收前面部分
            delete [] (_pstr - refKeynumber);
            _pstr = nullptr;
        }else{
            delerefKey();
        }
        cout<<"~ CowString"<<endl;
    }
    //拷贝构造
    CowString(const CowString&rhs)
    :_pstr(malloc(rhs._pstr)) //类内可以 类外不行
    {
        strcpy(_pstr,rhs._pstr);
        addrefKey();
        cout<<"CowString(const CowString&rhs)"<<endl;
    }
    //复制运算赋操作
    CowString& operator=(const CowString&rhs){
        //注意自复制问题
        if(this!=&rhs){
            //要删掉本身的记录数据的
            release(); //不一定回收空间，但至少能-1；
            //浅拷贝
            _pstr = rhs._pstr;
            addrefKey();
        }
        return *this;
    }
    //<<
    friend
    ostream& operator<<(ostream&os,const CowString &rhs); 

    //[]
    charProxy operator[](int index){ //这里一个错误 返回的不是& 是直接拷贝，因为是临时的值
        //实际上是返回的
        return charProxy(*this,index);
    }

    //为了解决charProxy的问题
    friend
    ostream& operator<<(ostream&os,const CowString::charProxy&rhs);

private: 
    //static const int refKeynumber = 4; //不是static 每个对象需要调用才能使用 也就是 this.refkeynumber
    const int refKeynumber = 4;
    //字符串
    char* _pstr = nullptr;
};

ostream& operator<<(ostream&os,const CowString &rhs){
    os<<rhs._pstr;
    //不好意思这里没有返回值
    return os;
}

//返回一个charProxy的对象
ostream& operator<<(ostream&os,const CowString::charProxy&rhs ){
    cout<<rhs._self._pstr[rhs.index];
}





void test0(){
    CowString str1("nihao");
    //sleep(1);
    cout<<str1.use_count()<<endl;
    CowString str2("hello");
    cout<<str2.use_count()<<endl;
    cout<<str1<<endl;
    cout<<str2<<endl;
    cout<<endl;
    str2 = str1;
    str1[1] = 'x'; //改变了值
    cout<<str1<<endl;
    cout<<str2<<endl;
    cout<<str2.use_count()<<endl;
    cout<<str1.use_count()<<endl;
    
}

int main(void)
{   
    //这个代码的问题 就是[] 访问会出问题 写一下
    test0();
    return 0;
}